package com.example.common.core;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.common.util.auto_wrapper.AutoWhereUtil;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @author zjarlin
 * @since 2023/3/18 11:28
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class BaseSimpleService<S extends IService<PO>, PO> {

    private S service;

    public static <S extends IService<PO>, PO> BaseSimpleService<S, PO> of(S service) {
        return new BaseSimpleService<>(service);
    }

    public List<PO> listConditionalQuery(@Valid @RequestBody PO vo) {
        LambdaQueryWrapper<PO> lambdaQueryWrapper = getConditionFun().apply(vo);
        return service.list(lambdaQueryWrapper);
    }

    protected Function<PO, LambdaQueryWrapper<PO>> getConditionFun() {
        return
            po -> {
                Class<?> poClass = po.getClass();
                return (LambdaQueryWrapper<PO>) AutoWhereUtil.lambdaQueryByField(poClass, po);
            };
    }

    /**
     * 分页查询
     *
     * @param vo
     * @param pageNo
     * @param pageSize
     * @return {@link IPage }<{@link PO }>
     * @author zjarlin
     * @since 2023/03/18
     */
    public IPage<PO> page(PO vo,
                          @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                          @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize
    ) {
        Page<PO> page = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<PO> lambdaQueryWrapper = getConditionFun().apply(vo);
        Page<PO> pages = service.page(page, lambdaQueryWrapper);
        return pages;
    }

    /**
     * 查询所有
     *
     * @return {@link Result }<{@link List }<{@link PO }>>
     * @author zjarlin
     * @since 2023/03/18
     */
    public List<PO> listAll() {
        return service.list();

    }

    /**
     * id查询单条
     *
     * @param id 入参
     * @return {@link Result }<{@link PO }>
     * @author zjarlin
     * @since 2023/03/18
     */
    public PO queryById(@RequestParam Serializable id) {
        final PO byId = service.getById(id);
        return byId;
    }

    /**
     * 添加
     *
     * @param po 入参
     * @return boolean
     * @author zjarlin
     * @since 2023/03/18
     */
    public boolean add(@RequestBody PO po) {
        return service.save(po);
    }

    /**
     * 带唯一索引的新增
     *
     * @param po 入参
     * @return {@link Result }<{@link Boolean }>
     * @author zjarlin
     * @since 2023/03/18
     */
    public boolean addIfAbsent(@RequestBody PO po) {
        //拿到注解上的提示消息
        String allQuniqueMsg = getAllQuniqueMsg(po);
        if (dataAlreadyExists(po)) {
            throw new IllegalArgumentException(allQuniqueMsg);//这里拿不到哪个字段eq或者like出来的数据存在!!
        }
        return service.save(po);
    }

    /**
     * 得到联合索引提示消息
     *
     * @param po 在签证官 入参
     * @return {@link String }
     * @author zjarlin
     * @since 2023/03/18
     */
    protected String getAllQuniqueMsg(PO po) {
        Class<?> aClass = po.getClass();
        UniqueMsg uniqueMsg = aClass.getAnnotation(UniqueMsg.class);
        if (Objects.nonNull(uniqueMsg)) {
            String value1 = uniqueMsg.value();
            String msg = uniqueMsg.msg();
            return Stream.of(value1, msg).findAny().orElse("");
        }
        Field[] declaredFields = aClass.getDeclaredFields();
        List<Field> collect = Arrays.stream(declaredFields)
            .filter(field -> {
                Annotation annotation = field.getAnnotation(UniqueMsg.class);
                return Objects.nonNull(annotation);
            }).collect(Collectors.toList());

        return collect.stream()
            .map(field -> {
                    field.setAccessible(true);
                    UniqueMsg annotation = field.getAnnotation(UniqueMsg.class);
                    return annotation.value();
                }
            ).collect(Collectors.joining(","));

    }

    //

    protected boolean dataAlreadyExists(PO po) {
        LambdaQueryWrapper<PO> apply = getUniqueConditionFun().apply(po);
        List<PO> list = service.list(apply);
        return CollUtil.isNotEmpty(list);
    }

    //唯一性校验默认对PO上加了注解的条件校验
    protected Function<PO, LambdaQueryWrapper<PO>> getUniqueConditionFun() {
        return
            po -> {
                Class<?> poClass = po.getClass();
                return (LambdaQueryWrapper<PO>) AutoWhereUtil.lambdaQueryByAnnotation(poClass, po);
            };
    }

    /**
     * 修改-单条
     *
     * @param po 在签证官 入参
     * @return {@link Result }<{@link Boolean }>
     * @author zjarlin
     * @since 2023/03/18
     */
    public boolean edit(@RequestBody PO po) {
        final boolean body = service.updateById(po);
        return body;
    }

    /**
     * 删除-单条
     *
     * @param id id 入参
     * @return boolean
     * @author zjarlin
     * @since 2023/03/18
     *///    @ApiOperation("删除-单条")
    public boolean delete(@RequestParam Serializable id) {
        return service.removeById(id);
    }

    /**
     * delete-按id批量删除(支持逗号隔开)
     *
     * @param idList id列表 入参
     * @return {@link Result }<{@link Boolean }>
     * @author zjarlin
     * @since 2023/03/18
     */
    public boolean deleteByIdList(@RequestParam List<Long> idList) {
        return service.removeByIds(idList);
    }

}


